import Tablero
import Damas
import HUnit
import Maybe

-- evaluar t para correr todos los tests
t = runTestTT allTests

allTests = test [ 
	"triviales" ~: testsTriviales,
	"ejercicio 1" ~: testsEjercicio1,
	"ejercicio 2" ~: testsEjercicio2,
	"ejercicio 3" ~: testsEjercicio3,
	-- "ejercicios 5" ~: testsEjercicio5, no vamos a testear un fold. 
	-- Si tiene un error, se detectará en el testing de las funciones que lo utilizan
	"ejercicio 8" ~: testsEjercicio8
	]

testsTriviales = test [
	1 ~=? 1,
	2 ~=? 2,
	[1,2] ~=? [1,2],
	[1,2] ~~? [2,1]
	]

testsEjercicio1 = test [ 
	-- Ninguna posicion tiene fichas. 
	-- Es muy trivial viendo la función, pero nunca está de más ;-) (sobre todo pensando en Test Driven Development)
	Nothing ~=? contenido a_1 vacio,
	Nothing ~=? contenido a_2 vacio,
	Nothing ~=? contenido a_3 vacio,
	Nothing ~=? contenido a_4 vacio,
	Nothing ~=? contenido a_5 vacio,
	Nothing ~=? contenido a_6 vacio,
	Nothing ~=? contenido a_7 vacio,
	Nothing ~=? contenido a_8 vacio,

	Nothing ~=? contenido b_1 vacio,
	Nothing ~=? contenido b_2 vacio,
	Nothing ~=? contenido b_3 vacio,
	Nothing ~=? contenido b_4 vacio,
	Nothing ~=? contenido b_5 vacio,
	Nothing ~=? contenido b_6 vacio,
	Nothing ~=? contenido b_7 vacio,
	Nothing ~=? contenido b_8 vacio,

	Nothing ~=? contenido c_1 vacio,
	Nothing ~=? contenido c_2 vacio,
	Nothing ~=? contenido c_3 vacio,
	Nothing ~=? contenido c_4 vacio,
	Nothing ~=? contenido c_5 vacio,
	Nothing ~=? contenido c_6 vacio,
	Nothing ~=? contenido c_7 vacio,
	Nothing ~=? contenido c_8 vacio,

	Nothing ~=? contenido d_1 vacio,
	Nothing ~=? contenido d_2 vacio,
	Nothing ~=? contenido d_3 vacio,
	Nothing ~=? contenido d_4 vacio,
	Nothing ~=? contenido d_5 vacio,
	Nothing ~=? contenido d_6 vacio,
	Nothing ~=? contenido d_7 vacio,
	Nothing ~=? contenido d_8 vacio,
	
	Nothing ~=? contenido e_1 vacio,
	Nothing ~=? contenido e_2 vacio,
	Nothing ~=? contenido e_3 vacio,
	Nothing ~=? contenido e_4 vacio,
	Nothing ~=? contenido e_5 vacio,
	Nothing ~=? contenido e_6 vacio,
	Nothing ~=? contenido e_7 vacio,
	Nothing ~=? contenido e_8 vacio,

	Nothing ~=? contenido f_1 vacio,
	Nothing ~=? contenido f_2 vacio,
	Nothing ~=? contenido f_3 vacio,
	Nothing ~=? contenido f_4 vacio,
	Nothing ~=? contenido f_5 vacio,
	Nothing ~=? contenido f_6 vacio,
	Nothing ~=? contenido f_7 vacio,
	Nothing ~=? contenido f_8 vacio,
	Nothing ~=? contenido f_1 vacio,

	Nothing ~=? contenido g_1 vacio,
	Nothing ~=? contenido g_2 vacio,
	Nothing ~=? contenido g_3 vacio,
	Nothing ~=? contenido g_4 vacio,
	Nothing ~=? contenido g_5 vacio,
	Nothing ~=? contenido g_6 vacio,
	Nothing ~=? contenido g_7 vacio,
	Nothing ~=? contenido g_8 vacio,

	Nothing ~=? contenido h_1 vacio,
	Nothing ~=? contenido h_2 vacio,
	Nothing ~=? contenido h_3 vacio,
	Nothing ~=? contenido h_4 vacio,
	Nothing ~=? contenido h_5 vacio,
	Nothing ~=? contenido h_6 vacio,
	Nothing ~=? contenido h_7 vacio,
	Nothing ~=? contenido h_8 vacio
	]

testsEjercicio2 = test [
	-- Una posición fuera del tablero no tiene fichas
	Nothing ~=? contenido h_9 vacio,
	-- Ponemos una ficha en una casilla y preguntamos por otra vacia. 
	Nothing ~=? contenido d_5 (poner d_4 _n vacio),
	-- Ponemos una ficha y preguntamos por ella
	Just _n ~=? contenido d_5 (poner d_5 _n vacio),
	-- Ponemos dos fichas en el mismo lugar, y preguntamos por la posicion	
	Just _N ~=? contenido d_5 (poner d_5 _N (poner d_5 _n vacio)),
	-- Ponemos la misma ficha dos veces, y preguntamos por la posicion
	contenido d_5 (poner d_5 _n vacio) ~=? contenido d_5 (poner d_5 _n (poner d_5 _n vacio)),
	-- Ponemos una ficha fuera del tablero y preguntamos por ella
	Just _n ~=? contenido h_9 (poner h_9 _n vacio),
	
	-- Sacamos una ficha inexistente (casilla vacia), y preguntamos por la posición
	Nothing ~=? contenido d_6 (sacar d_6 vacio),
	-- Ponemos y sacamos la misma ficha, luego preguntamos por ella
	Nothing ~=? contenido d_5 (sacar d_5 (poner d_5 _n vacio)),
	-- Ponemos una ficha y la sacamos dos veces, luego preguntamos por la posicion
	contenido d_5 (sacar d_5 vacio) ~=? contenido d_5 (sacar d_5 (sacar d_5 (poner d_5 _n vacio)))
	]

testsEjercicio3 = test [
	-- Tests de precondiciones
	-- La casilla de origen está fuera del tablero
	Nothing ~=? mover (M h_9 BL) (J Negra (poner h_9 _n vacio)),
	-- La casilla destino está fuera del tablero
	Nothing ~=? mover (M h_1 BL) (J Negra (poner h_1 _N vacio)),
	-- No hay ficha en la posición a mover
	Nothing ~=? mover (M h_1 TL) (J Negra (poner g_2 _N vacio)),
	-- La ficha a mover no coincide con el color del turno
	Nothing ~=? mover (M h_1 TL) (J Blanca (poner h_1 _N vacio)),
	-- Una ficha simple no puede mover hacia atras
	Nothing ~=? mover (M d_5 TL) (J Negra (poner d_5 _n vacio)),
	Nothing ~=? mover (M d_5 TR) (J Negra (poner d_5 _n vacio)),
	-- La casilla destino está ocupada por una ficha del oponente, y la tiene "cubierta" con otra detrás
	Nothing ~=? mover (M d_5 TL) (J Blanca t_simple_blanca_no_come),
	Nothing ~=? mover (M d_5 TL) (J Blanca t_reina_blanca_no_come),
	-- La casilla destino está ocupada por una ficha del mismo color
	Nothing ~=? mover (M d_5 TL) (J Blanca t_simple_blanca_no_come_2),
	Nothing ~=? mover (M d_5 TL) (J Blanca t_reina_blanca_no_come_2),
	
	-- Tests de movimientos, comidas y coronaciones
	-- Coronación de blanca
	Just (J Negra t_resultado_simple_blanca_corona) ~=? mover (M a_6 TR) (J Blanca t_simple_blanca_corona),
	-- A pesar de poder comer dos, en el tradicional juego de damas, debe comer sólo una
	Just (J Negra t_resultado_reina_blanca_come_una) ~=? mover (M c_4 TR) (J Blanca t_reina_blanca_come_una),
	-- Coronoción de reina negra
	Just (J Blanca t_resultado_reina_negra_corona) ~=? mover (M h_3 BL) (J Negra t_reina_negra_corona),
	-- Reina negra come hacia atras
	Just (J Blanca t_resultado_reina_negra_come_una_atras) ~=? mover (M h_3 TL) (J Negra t_reina_negra_come_una_atras),
	-- Reina negra no come hacia atras
	Just (J Blanca t_resultado_reina_negra_no_come_atras) ~=? mover (M h_3 TL) (J Negra t_reina_negra_no_come_atras)
	]

testsEjercicio8 = test [
	-- Pierde por bloqueo
	Just Negra ~=? ganador (J Blanca t_blancas_bloqueadas),
	-- Comió todo
	Just Negra ~=? ganador (J Blanca (poner d_4 _n vacio))
	]

-- idem ~=? pero sin importar el orden
(~~?) :: (Ord a, Eq a, Show a) => [a] -> [a] -> Test
expected ~~? actual = (sort expected) ~=? (sort actual)
	where
		sort = foldl (\r e -> push r e) []
		push r e = (filter (e<=) r) ++ [e] ++ (filter (e>) r)

(~~) :: (Ord a, Eq a, Show a) => [a] -> [a] -> Bool
expected ~~ actual = (sort expected) == (sort actual)
	where
		sort = foldl (\r e -> push r e) []
		push r e = (filter (e<=) r) ++ [e] ++ (filter (e>) r)

-- constantes para que los tests sean más legibles		

-- Fichas
_n = Simple Negra
_N = Reina Negra
_b = Simple Blanca
_B = Reina Blanca

-- Posiciones dentro del Tablero de Damas
a_1 = ('a',1::Int)
b_1 = ('b',1::Int)
c_1 = ('c',1::Int)
d_1 = ('d',1::Int)
e_1 = ('e',1::Int)
f_1 = ('f',1::Int)
g_1 = ('g',1::Int)
h_1 = ('h',1::Int)

a_2 = ('a',2::Int)
b_2 = ('b',2::Int)
c_2 = ('c',2::Int)
d_2 = ('d',2::Int)
e_2 = ('e',2::Int)
f_2 = ('f',2::Int)
g_2 = ('g',2::Int)
h_2 = ('h',2::Int)

a_3 = ('a',3::Int)
b_3 = ('b',3::Int)
c_3 = ('c',3::Int)
d_3 = ('d',3::Int)
e_3 = ('e',3::Int)
f_3 = ('f',3::Int)
g_3 = ('g',3::Int)
h_3 = ('h',3::Int)

a_4 = ('a',4::Int)
b_4 = ('b',4::Int)
c_4 = ('c',4::Int)
d_4 = ('d',4::Int)
e_4 = ('e',4::Int)
f_4 = ('f',4::Int)
g_4 = ('g',4::Int)
h_4 = ('h',4::Int)

a_5 = ('a',5::Int)
b_5 = ('b',5::Int)
c_5 = ('c',5::Int)
d_5 = ('d',5::Int)
e_5 = ('e',5::Int)
f_5 = ('f',5::Int)
g_5 = ('g',5::Int)
h_5 = ('h',5::Int)

a_6 = ('a',6::Int)
b_6 = ('b',6::Int)
c_6 = ('c',6::Int)
d_6 = ('d',6::Int)
e_6 = ('e',6::Int)
f_6 = ('f',6::Int)
g_6 = ('g',6::Int)
h_6 = ('h',6::Int)

a_7 = ('a',7::Int)
b_7 = ('b',7::Int)
c_7 = ('c',7::Int)
d_7 = ('d',7::Int)
e_7 = ('e',7::Int)
f_7 = ('f',7::Int)
g_7 = ('g',7::Int)
h_7 = ('h',7::Int)

a_8 = ('a',8::Int)
b_8 = ('b',8::Int)
c_8 = ('c',8::Int)
d_8 = ('d',8::Int)
e_8 = ('e',8::Int)
f_8 = ('f',8::Int)
g_8 = ('g',8::Int)
h_8 = ('h',8::Int)

-- Posiciones fuera del Tablero de Damas
h_9 = ('h',9::Int)

-- Tableros
t_simple_blanca_no_come = poner b_7 _n (poner c_6 _n (poner d_5 _b vacio))
--   a b c d e f g h  
--  ----------------- 
--8 | | | | | | | | | 8
--7 | |n| | | | | | | 7
--6 | | |n| | | | | | 6
--5 | | | |b| | | | | 5
--4 | | | | | | | | | 4
--3 | | | | | | | | | 3
--2 | | | | | | | | | 2
--1 | | | | | | | | | 1
--  ----------------- 
--   a b c d e f g h  

t_reina_blanca_no_come = poner b_7 _n (poner c_6 _n (poner d_5 _B vacio))
--   a b c d e f g h  
--  ----------------- 
--8 | | | | | | | | | 8
--7 | |n| | | | | | | 7
--6 | | |n| | | | | | 6
--5 | | | |B| | | | | 5
--4 | | | | | | | | | 4
--3 | | | | | | | | | 3
--2 | | | | | | | | | 2
--1 | | | | | | | | | 1
--  ----------------- 
--   a b c d e f g h  

t_simple_blanca_no_come_2 = poner c_6 _b (poner d_5 _b vacio)
--   a b c d e f g h  
--  ----------------- 
--8 | | | | | | | | | 8
--7 | | | | | | | | | 7
--6 | | |b| | | | | | 6
--5 | | | |b| | | | | 5
--4 | | | | | | | | | 4
--3 | | | | | | | | | 3
--2 | | | | | | | | | 2
--1 | | | | | | | | | 1
--  ----------------- 
--   a b c d e f g h  

t_reina_blanca_no_come_2 = poner c_6 _b (poner d_5 _B vacio)
--   a b c d e f g h  
--  ----------------- 
--8 | | | | | | | | | 8
--7 | | | | | | | | | 7
--6 | | |b| | | | | | 6
--5 | | | |B| | | | | 5
--4 | | | | | | | | | 4
--3 | | | | | | | | | 3
--2 | | | | | | | | | 2
--1 | | | | | | | | | 1
--  ----------------- 
--   a b c d e f g h  

t_simple_blanca_corona = poner b_7 _n (poner a_6 _b vacio)
t_resultado_simple_blanca_corona = poner c_8 _B vacio
--   a b c d e f g h  
--  ----------------- 
--8 | | | | | | | | | 8
--7 | |n| | | | | | | 7
--6 |b| | | | | | | | 6
--5 | | | | | | | | | 5
--4 | | | | | | | | | 4
--3 | | | | | | | | | 3
--2 | | | | | | | | | 2
--1 | | | | | | | | | 1
--  ----------------- 
--   a b c d e f g h  

t_reina_blanca_come_una = poner c_4 _B (poner d_5 _n (poner f_7 _n vacio))
t_resultado_reina_blanca_come_una = poner e_6 _B (poner f_7 _n vacio)
--   a b c d e f g h  
--  ----------------- 
--8 | | | | | | | | | 8
--7 | | | | | |n| | | 7
--6 | | | | | | | | | 6
--5 | | | |n| | | | | 5
--4 | | |B| | | | | | 4
--3 | | | | | | | | | 3
--2 | | | | | | | | | 2
--1 | | | | | | | | | 1
--  ----------------- 
--   a b c d e f g h  

t_reina_negra_corona = poner g_2 _b (poner h_3 _N vacio)
t_resultado_reina_negra_corona = poner f_1 _N vacio
--   a b c d e f g h  
--  ----------------- 
--8 | | | | | | | | | 8
--7 | | | | | | | | | 7
--6 | | | | | | | | | 6
--5 | | | | | | | | | 5
--4 | | | | | | | | | 4
--3 | | | | | | | |N| 3
--2 | | | | | | |b| | 2
--1 | | | | | | | | | 1
--  ----------------- 
--   a b c d e f g h  

t_reina_negra_come_una_atras = poner g_4 _b (poner h_3 _N vacio)
t_resultado_reina_negra_come_una_atras = poner f_5 _N vacio
--   a b c d e f g h  
--  ----------------- 
--8 | | | | | | | | | 8
--7 | | | | | | | | | 7
--6 | | | | | | | | | 6
--5 | | | | | | | | | 5
--4 | | | | | | |b| | 4
--3 | | | | | | | |N| 3
--2 | | | | | | | | | 2
--1 | | | | | | | | | 1
--  ----------------- 
--   a b c d e f g h  

t_reina_negra_no_come_atras = poner f_5 _b (poner h_3 _N vacio)
t_resultado_reina_negra_no_come_atras = poner f_5 _b (poner g_4 _N vacio)
--   a b c d e f g h  
--  ----------------- 
--8 | | | | | | | | | 8
--7 | | | | | | | | | 7
--6 | | | | | | | | | 6
--5 | | | | | |b| | | 5
--4 | | | | | | | | | 4
--3 | | | | | | | |N| 3
--2 | | | | | | | | | 2
--1 | | | | | | | | | 1
--  ----------------- 
--   a b c d e f g h  

t_blancas_bloqueadas = poner d_4 _b (poner c_5 _b (poner e_5 _b (poner b_6 _n (poner d_6 _n (poner f_6 _n (poner a_7 _n (poner c_7 _n (poner e_7 _n (poner g_7 _n vacio)))))))))
--   a b c d e f g h  
--  ----------------- 
--8 | | | | | | | | | 8
--7 |n| |n| |n| |n| | 7
--6 | |n| |n| |n| | | 6
--5 | | |b| |b| | | | 5
--4 | | | |b| | | | | 4
--3 | | | | | | | | | 3
--2 | | | | | | | | | 2
--1 | | | | | | | | | 1
--  ----------------- 
--   a b c d e f g h  